package com.gitee.wsl.ext.string

import kotlin.math.min

fun String.prefixIfNotEmpty(s: String): String = (s + this).takeIf { this.isNotEmpty() } ?: this

fun String.postfixIfNotEmpty(s: String): String = (this + s).takeIf { this.isNotEmpty() } ?: this

fun String.surroundIfNotEmpty(
    prefix: String,
    postFix: String,
): String = this.prefixIfNotEmpty(prefix).postfixIfNotEmpty(postFix)

/**
 * @param prefix prefix to remove
 * @param ignoreCase whether to ignore case when searching for the prefix
 * @return a pair of this string without [prefix] and a boolean value indicating whether the prefix was removed.
 *         If the prefix is not present, the string is returned as is and the boolean value is `false`
 */
fun String.removeOptionalPrefix(
    prefix: String,
    ignoreCase: Boolean = false,
): Pair<String, Boolean> {
    return if (startsWith(prefix, ignoreCase)) {
        substring(prefix.length) to true
    } else {
        this to false
    }
}

fun String.ensurePrefix(prefix: String): String = when {
    startsWith(prefix) -> this
    else -> "$prefix$this"
}

fun String.ensureSuffix(suffix: String): String = when {
    endsWith(suffix) -> this
    else -> "$this$suffix"
}


/**
 * Finds the common prefix of two Strings in a Pair.
 *
 * @return The common prefix String.
 */
fun Pair<String, String>.commonPrefix(): String {
    val (left, right) = this
    val min = min(left.length, right.length)
    for (i in 0 until min) {
        if (left[i] != right[i]) {
            return left.substring(0, i)
        }
    }
    return left.substring(0, min)
}


/**
 * 去掉首部指定长度的字符串并将剩余字符串首字母小写<br></br>
 * 例如：str=setName, prefix=set =》 return name
 *
 * @param prefix 前缀
 * @return 处理后的字符串，不符合规范返回null
 */
fun String.removePreAndLowerFirst(prefix: CharSequence): String {
    return removePrefix(prefix).lowerFirstLetter()
}


/**
 * 去掉指定所有前缀，如：
 * <pre>`str=abcdef, prefix=ab => return cdef
 * str=ababcdef, prefix=ab => return cdef
 * str=ababcdef, prefix="" => return ababcdef
 * str=ababcdef, prefix=null => return ababcdef
`</pre> *
 *
 * @param str    字符串，空返回原字符串
 * @param prefix 前缀，空返回原字符串
 * @return 去掉所有前缀的字符串，若前缀不是 preffix， 返回原字符串
 * @since 5.8.30
 */
fun CharSequence.removeAllPrefix(prefix: CharSequence): String {
    val str = this
    if (isEmpty() || prefix.isEmpty()) {
        return str.toString()
    }

    val prefixStr = prefix.toString()
    val prefixLength = prefixStr.length

    val str2 = str.toString()
    var toIndex = 0
    while (str2.startsWith(prefixStr, toIndex)) {
        toIndex += prefixLength
    }
    return substring(toIndex)
}


/**
 * 去掉指定所有后缀，如：
 * <pre>`str=11abab, suffix=ab => return 11
 * str=11ab, suffix=ab => return 11
 * str=11ab, suffix="" => return 11ab
 * str=11ab, suffix=null => return 11ab
`</pre> *
 *
 * @param str    字符串，空返回原字符串
 * @param suffix 后缀字符串，空返回原字符串
 * @return 去掉所有后缀的字符串，若后缀不是 suffix， 返回原字符串
 * @since 5.8.30
 */
fun CharSequence.removeAllSuffix(suffix: CharSequence): String {
    val str = this
    if (isEmpty() || suffix.isEmpty()) {
        return str.toString()
    }

    val suffixStr = suffix.toString()
    val suffixLength = suffixStr.length

    val str2 = str.toString()
    var toIndex = str2.length
    while (str2.startsWith(suffixStr, toIndex - suffixLength)) {
        toIndex -= suffixLength
    }
    return str2.substring(0,toIndex)
}


/**
 * 忽略大小写去掉指定前缀
 *
 * @param str    字符串
 * @param prefix 前缀
 * @return 切掉后的字符串，若前缀不是 prefix， 返回原字符串
 */
fun CharSequence.removePrefixIgnoreCase(prefix: CharSequence): String {
    if (isEmpty() || prefix.isEmpty()) {
        return toString()
    }

    val str2 = toString()
    if (startWithIgnoreCase(prefix)) {
        return substring( prefix.length) // 截取后半段
    }
    return str2
}

// 判断是否是合法的数字编号（如 "2" 或 "3.2.1"）

fun String.isNumberedPrefix(): Boolean {
    val s = this
    if (s.isEmpty()) {
        return false
    }

    var hasDigit = false

    for (i in 0..<s.length) {
        val c = s.get(i)

        if (c == '.') {
            // 点号前必须有数字，且不能是连续的点号
            if (!hasDigit || i == s.length - 1 || s.get(i + 1) == '.') {
                return false
            }
            hasDigit = false // 重置数字标志
        } else if (c.isDigit()) {
            hasDigit = true
        } else {
            // 非数字非点号字符
            return false
        }
    }

    return hasDigit // 确保最后一部分是数字
}